<!DOCTYPE html>
<html>
<!--
Copyright 2012 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.labs.observe.SimpleObservable</title>
<script src="../../base.js"></script>
<script>
  goog.require('goog.dispose');
  goog.require('goog.labs.observe.Observer');
  goog.require('goog.labs.observe.SimpleObservable');
  goog.require('goog.testing.jsunit');
  goog.require('goog.testing.recordFunction');
</script>
</head>
<body>
<script>
var observable;


function setUp() {
  observable = new goog.labs.observe.SimpleObservable();
}


function tearDown() {
  goog.dispose(observable);
}


function testObserve() {
  var observerFn = goog.testing.recordFunction();
  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn));
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
}


function testObserveWithTheSameObserver() {
  var observerFn = goog.testing.recordFunction();
  var observer = goog.labs.observe.Observer.fromFunction(observerFn);

  assertTrue(observable.observe(observer));
  assertFalse(observable.observe(observer));
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
  observerFn.reset();

  // observer.equals(observer2) == true
  var observer2 = goog.labs.observe.Observer.fromFunction(observerFn);
  assertFalse(observable.observe(observer2));
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
}


function testMultipleObservers() {
  var observerFn = goog.testing.recordFunction();
  var observerFn2 = goog.testing.recordFunction();
  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn));
  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn2));
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
  assertEquals(1, observerFn2.getCallCount());
}


function testUnobserve() {
  var observerFn = goog.testing.recordFunction();
  var observer = goog.labs.observe.Observer.fromFunction(observerFn);
  observable.observe(observer);
  assertTrue(observable.unobserve(observer));
  observable.notify();
  assertEquals(0, observerFn.getCallCount());
  assertFalse(observable.unobserve(observer));
}


function testNotice() {
  var observerFn = goog.testing.recordFunction(function(notice) {
    assertNotNull(notice);
    assertEquals(observable, notice.getObservable());
    assertUndefined(notice.getData());
  });

  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn));
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
}


function testNoticeWithData() {
  var data = {foo: 1};
  var observerFn = goog.testing.recordFunction(function(notice) {
    assertNotNull(notice);
    assertEquals(observable, notice.getObservable());
    assertEquals(data, notice.getData());
  });

  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn));
  observable.notify(data);
  assertEquals(1, observerFn.getCallCount());
}


function testUnobserveWhileObserverIsFiring() {
  var observerFn = goog.testing.recordFunction(function() {
    observable.unobserve(observer);
    assertFalse(observable.unobserve(observer));
  });
  var observer = goog.labs.observe.Observer.fromFunction(observerFn);
  var observerFn2 = goog.testing.recordFunction();
  observable.observe(observer);
  observable.observe(goog.labs.observe.Observer.fromFunction(observerFn2));

  observable.notify();
  assertEquals(1, observerFn.getCallCount());
  assertEquals(1, observerFn2.getCallCount());

  observable.notify();
  assertEquals(1, observerFn.getCallCount());
  assertEquals(2, observerFn2.getCallCount());
}


function testSimpleObservableAsComposition() {
  var observable = new ActualObservable();

  var observerFn = goog.testing.recordFunction(function(notice) {
    assertNotNull(notice);
    assertEquals(observable, notice.getObservable());
    assertUndefined(notice.getData());
  });
  var observer = goog.labs.observe.Observer.fromFunction(observerFn);

  observable.observe(observer);
  observable.notify();
  assertEquals(1, observerFn.getCallCount());
  observerFn.reset();
}


function testDispose() {
  var observerFn = function() {};
  var observer = goog.labs.observe.Observer.fromFunction(observerFn);

  observable.dispose();
  assertThrows(function() {
    observable.observe(observer);
  });
  assertThrows(function() {
    observable.notify();
  });
  assertThrows(function() {
    observable.observe(observer);
  });
}



/**
 * @constructor
 * @extends {goog.Disposable}
 */
ActualObservable = function() {
  goog.base(this);
  this.observable_ = new goog.labs.observe.SimpleObservable(this);
  this.registerDisposable(this.observable_);
};
goog.inherits(ActualObservable, goog.Disposable);


ActualObservable.prototype.observe = function(type, observer) {
  this.observable_.observe(type, observer);
};


ActualObservable.prototype.unobserve = function(type, observer) {
  this.observable_.unobserve(type, observer);
};


ActualObservable.prototype.notify = function(type, opt_data) {
  this.observable_.notify(type, opt_data);
};

</script>
</body>
</html>
